package com.dfhc.pub.service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.collections.CollectionUtils;
import org.quickbundle.project.RmProjectHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.dfhc.ISystemConstant;
import com.dfhc.PjException;
import com.dfhc.util.ConvertHelper;
import com.dfhc.util.DateUtil;
import com.dfhc.util.JsonToMap;
import com.dfhc.util.StringHelper;
import com.dfhc.wk.frontflowdef.dao.FrontFlowDefDao;
import com.dfhc.wk.frontflowdef.vo.FrontFlowDefVo;

@Service
@Transactional(readOnly=true)
/**
 * 将自定义流程的json强行转为后台固定流程xml
 * @author dfhc
 *
 */
public class FlowJsonToXmlService {

	@Autowired
	private PubParamService pubParamService;
	@Autowired
    private  RepositoryService repositoryService;
	@Autowired
    private  FrontFlowDefDao frontFlowDefDao;
	
	
	/**
	 * 将前台json 存入数据库，并转为xml 部署
	 * @param jsonStr
	 */
	public void  doDeployFlow(String jsonStr){
		Map<String,Object> jsonMap=JsonToMap.parseJSON2Map(jsonStr);
		Map<String,Object> processMap=doFlwJsonToXml(jsonMap);
		

		String xml=(String)processMap.get("xml");
		String processName=(String)processMap.get("processName");
		String fileName=UUID.randomUUID().toString()+ISystemConstant.FLOW_FILE_SUFFIX;
		
		  try {
			    DeploymentBuilder deployment = repositoryService.createDeployment();
				InputStream fileInputStream=getStringStream(xml);
				if(fileInputStream==null){
					
					throw  new PjException("流程图格式不正确");
				}
				deployment.addInputStream(fileName, fileInputStream);
				
				FrontFlowDefVo vo=new FrontFlowDefVo();
				vo.setProcDefContent(jsonStr);
				vo.setCreate_time(DateUtil.getNowTimestamp());//创建时间
				vo.setProcName(processName);
				
				frontFlowDefDao.insert(vo);
//				String processName1 = fileName;
//				byte[] bpmnBytes  = convertStringToBytes(xml);
//			    String xml1 = new String(bpmnBytes);
//				Deployment deployment1 = repositoryService.createDeployment().name(processName).addString(processName1, xml1).deploy();
//				System.out.println("deploy id:"+deployment1.getId());
			    Deployment deployment1 = deployment.deploy();
			    if(deployment1 != null){
	    			ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment1.getId()).singleResult();
					if(processDefinition != null){
						vo.setProcDefId(processDefinition.getId());
						vo.setFormTemplateId(processMap.get("formTemplateId") == null?"":processMap.get("formTemplateId").toString());
						vo.setFormTemplateName(processMap.get("formTemplateName") == null?"":processMap.get("formTemplateName").toString());
						frontFlowDefDao.update(vo);
					}
			    }
		  }catch (Exception e) {
			// TODO: handle exception
			  RmProjectHelper.logError(e.getCause(), e.getMessage());
			  e.printStackTrace();
		}
		
		
	}
	
	/**
	 * 将前台的数据json转为后台固定流程xml
	 * @param jsonStr
	 * @return
	 */
	private  Map<String,Object> doFlwJsonToXml(Map<String,Object> jsonMap){
		StringBuilder xml=new StringBuilder();//存放全部xml
		
		StringBuilder bpmndi=new StringBuilder();//存放流程节点位置信息
		
		
		xml.append(addXmlHead());//将xml头放入
		
		
		String props=(String)jsonMap.get("props");//获取流程实例信息
		
		Map<String,Object> processMap=resolveProcessName(props, bpmndi);
		String processXml=(String)processMap.get("xml");
		String processName=(String)processMap.get("processName");//流程名称
		String formTemplateId = (String)processMap.get("formTemplateId");//表单模板Id
		String formTemplateName = (String)processMap.get("formTemplateName");//表单模板Id
		xml.append(processXml);//流程实体组装成xml；

		
		String paths=(String)jsonMap.get("paths");//获取流程路径
		String  states=(String)jsonMap.get("states");//获取流程节点
		if(StringHelper.isEmpty(states) || StringHelper.isEmpty(paths)){//任务节点为空或路径为空直接返回空串
			processMap.clear();
			return processMap;
		}
		
		String nodeMsg=doResolveNode(states, bpmndi);//解析任务节点位置信息和形状
		
		String flowPath=doResolveFlow(paths,bpmndi);//捷信流程线信息
		xml.append(nodeMsg);
		xml.append(flowPath);
		
		xml.append(bpmndi);
		xml.append(" \n\r </bpmndi:BPMNDiagram> \n\r </definitions> \n\r");
		
		
		System.out.println(xml);

		processMap.clear();
		processMap.put("xml", xml.toString());//存放json转换后的xml
		processMap.put("processName", processName);//存放流程明
		processMap.put("formTemplateId", formTemplateId);
		processMap.put("formTemplateName", formTemplateName);
		return processMap;
				
	}
	
	/**
	 * 将xml 转为文件流
	 * @param xml
	 * @return
	 */
	private  InputStream getStringStream(String xml){
		
		if(!StringHelper.isEmpty(xml)){
			
			ByteArrayInputStream tInputStringStream=null;
			XMLStreamReader reader = null;
			try {
				tInputStringStream = new ByteArrayInputStream(xml.getBytes("UTF-8"));				
				XMLInputFactory xmlFactory  = XMLInputFactory.newInstance();  
			    reader = xmlFactory.createXMLStreamReader(tInputStringStream);
				BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
				  
				 BpmnModel model = bpmnXMLConverter.convertToBpmnModel(reader);
				 byte[] bpmnBytes = bpmnXMLConverter.convertToXML(model,"GBK");
				 return new ByteArrayInputStream(bpmnBytes);				 
			} catch (UnsupportedEncodingException | XMLStreamException e) {
				// TODO Auto-generated catch block
				RmProjectHelper.logError(e.getCause(), e.getMessage());
			}finally{
				if(tInputStringStream!=null){
					try {
						tInputStringStream.close();
					} catch (IOException e) {
						e.printStackTrace();
						RmProjectHelper.logError(e.getCause(), e.getMessage());
					}
				}
				if(reader!=null){
					try {
						reader.close();
					} catch (XMLStreamException e) {
						e.printStackTrace();
						RmProjectHelper.logError(e.getCause(), e.getMessage());
					}
				}
			}
			
		}else{
			return null;
		}
		return null;
		
   }
	
	/**
	 * 新增activity 流程头
	 * @return
	 */
	private  String addXmlHead(){
		StringBuilder xmlHeader=new StringBuilder();
		xmlHeader.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n\r");
		xmlHeader.append("<definitions ");
		xmlHeader.append("xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\"  ");
		xmlHeader.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"  ");
		xmlHeader.append("xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"  ");
		xmlHeader.append("xmlns:activiti=\"http://activiti.org/bpmn\"   ");
		xmlHeader.append("xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\"  ");
		xmlHeader.append("xmlns:omgdc=\"http://www.omg.org/spec/DD/20100524/DC\"  ");
		xmlHeader.append("xmlns:omgdi=\"http://www.omg.org/spec/DD/20100524/DI\"   ");
		xmlHeader.append("typeLanguage=\"http://www.w3.org/2001/XMLSchema\"   ");
		xmlHeader.append("expressionLanguage=\"http://www.w3.org/1999/XPath\"    ");
		xmlHeader.append("targetNamespace=\"http://www.activiti.org/processdef\">\n\r ");
		
		return xmlHeader.toString();
	}
	
	/**
	 * 流程实例json字符串组装成流程实例xml
	 * @param
	 * @param bpmndi:流程位置信息
	 * @return
	 */
	private Map<String,Object>  resolveProcessName(String props,StringBuilder bpmndi){
		
		StringBuilder sb=new StringBuilder();
		
//		props:{props:{processId:{value:'ZD_DFHC_f8c05e6a-d1b3-4142-a0ad-710ec84b7209'},
//		name:{value:'测试自定义'},documentation:{value:'自定义流程测试'}}}
	//---解析流程名称
//	{states:{},paths:{},props:{}}:空值
		Map<String,Object> propsMap= JsonToMap.parseJSON2Map(props);//解析流程图属性
		props=(String)propsMap.get("props");
		if(StringHelper.isEmpty(props)){//说明流程图中流程名没有数据
			propsMap.clear();
			return propsMap;
//			sb.append(" <process id=\"process\" isExecutable=\"true\"> ");
			
		}else {
			
			
		    propsMap=JsonToMap.parseJSON2Map(props);//解析流程图属性
		    
		    props=(String)propsMap.get("processId");//获取历程id json对象
		    String  nameJson=(String)propsMap.get("name");//流程实例名称
		    String  docJson=(String)propsMap.get("documentation");//流程实例说明
		    String  formNameJson=(String)propsMap.get("formTemplateName");//流程实例说明
		    String  formIdJson=(String)propsMap.get("formTemplateId");//流程实例说明
		    
		    if(StringHelper.isEmpty(nameJson)){//流程名称不为空
		    	
		    	throw new PjException("流程名不能为空！");
		    }
		    propsMap=JsonToMap.parseJSON2Map(nameJson);//流程实例名称
		    if(propsMap.size()>0){
		    	
		    	nameJson=(String)propsMap.get("value");//流程实例名称
		    }
		    
		    if(!StringHelper.isEmpty(docJson)){//实例说明不为空
		    	
		    	propsMap=JsonToMap.parseJSON2Map(docJson);//流程实例说明
		    	docJson=(String)propsMap.get("value");//流程实例说明
		    }
		    if(!StringHelper.isEmpty(formNameJson)){//实例说明不为空
		    	
		    	propsMap=JsonToMap.parseJSON2Map(formNameJson);//流程实例说明
		    	formNameJson=(String)propsMap.get("value");//流程实例说明
		    }
		    if(!StringHelper.isEmpty(formIdJson)){//实例说明不为空
		    	
		    	propsMap=JsonToMap.parseJSON2Map(formIdJson);//流程实例说明
		    	formIdJson=(String)propsMap.get("value");//流程实例说明
		    }
		    
		    propsMap=JsonToMap.parseJSON2Map(props);//解析流程图属性
		    props=(String)propsMap.get("value");//获取到流程id
		    
		    //组装xml
		    sb.append(" <process id=\"");
		    sb.append(props);
		    sb.append("\" ");
		    sb.append(" name=\"");
		    sb.append(nameJson);
		    sb.append("\" ");
		    sb.append(" isExecutable=\"true\"> \n\r ");
		    
		    if(!StringHelper.isEmpty(docJson)){
		    	 sb.append(" <documentation>");
		    	 sb.append(docJson);
		    	 sb.append("</documentation> \n\r ");
		    }
		    if(!StringHelper.isEmpty(formNameJson)){
		    	 sb.append(" <formTemplateName>");
		    	 sb.append(formNameJson);
		    	 sb.append("</formTemplateName> \n\r ");
		    }
		    if(!StringHelper.isEmpty(formIdJson)){
		    	 sb.append(" <formTemplateId>");
		    	 sb.append(formIdJson);
		    	 sb.append("</formTemplateId> \n\r ");
		    }
//		     <bpmndi:BPMNDiagram id="BPMNDiagram_process">
//		    <bpmndi:BPMNPlane bpmnElement="process" id="BPMNPlane_process">
		    
	    	bpmndi.append(" <bpmndi:BPMNDiagram  id=\"BPMNDiagram_");
	    	bpmndi.append(props);
	    	bpmndi.append("\"> \n\r <bpmndi:BPMNPlane bpmnElement=\"");
	    	bpmndi.append(props);
	    	bpmndi.append("\"  id=\"BPMNPlane_");
	    	bpmndi.append(props);
	    	bpmndi.append("\"> \n\r");//组装流程图节点位置信息
		    
			
	    	propsMap.clear();
	    	propsMap.put("xml", sb.toString());
	    	propsMap.put("processName", nameJson);
	    	propsMap.put("formTemplateId", formIdJson);
	    	propsMap.put("formTemplateName", formNameJson);
	    	
	    	return propsMap;
		}
		
	}
	
	
	/**
	 * 
	 * @param states
	 * @param bpmndi：节点位置信息，节点形状
	 * @return
	 */
	private String doResolveNode(String states,StringBuilder bpmndi){
		
        Map<String,Object> processNodeMap= JsonToMap.parseJSON2Map(states);//解析任务节点
		
		if(processNodeMap==null || processNodeMap.size()==0){//任务节点为空
			return "";
		}
		
		StringBuilder sb=new StringBuilder();
		for(Map.Entry<String, Object> processNode : processNodeMap.entrySet()){//遍历流程图节点
			
			String id=processNode.getKey();//
			String nodeValue=(String)processNode.getValue();//节点值
			if(StringHelper.isEmpty(nodeValue)){//如果节点值为空直接返回空
				return "";
			}
			
			Map<String,Object> nodeMap=JsonToMap.parseJSON2Map(nodeValue);//解析任务节点
			
			String type=(String)nodeMap.get("type");
			
			if(StringHelper.isEmpty(type)){//节点类型为空直接返回
				
				return "";
			}
			String attr=(String)nodeMap.get("attr");//节点位置属性值
			
			if(StringHelper.isEmpty(attr)){//界定啊位置信息为空直接返回
				
				return "";
			}
			
			String nodeProps=(String)nodeMap.get("props");//节点属性值
			
			String nodeStr=resolveNodeProps(id, nodeProps, type);//获取组装好的任务节点
			
			String shapeMsg=resolveNodeShape(type,id, attr);//获取节点位置信息和形状
			
			bpmndi.append(shapeMsg);
			
			sb.append(nodeStr);
			
			
		}
//		TODO
//		bpmndi.append("\n\r</bpmndi:BPMNPlane> \n\r");
		
		return sb.toString();
		
	}
	
	/**
	 * 解析流程
	 * @param paths
	 * @param bpmndi
	 * @return
	 */
	private  String doResolveFlow(String paths,StringBuilder bpmndi){
		
		Map<String,Object> pathsNodeMap= JsonToMap.parseJSON2Map(paths);//解析路径
		
		if(pathsNodeMap==null || pathsNodeMap.size()==0){
			
			throw new PjException("流程图路径信息不能为空");
		}
		
		StringBuilder pathMsg=new StringBuilder(); 
		
		StringBuilder waypoint=new StringBuilder();
		for(Map.Entry<String, Object> entry:pathsNodeMap.entrySet() ){
			
			String  pathId=entry.getKey();//获取id
			String value =(String)entry.getValue();
			
			Map<String,Object> pathMsgMap=JsonToMap.parseJSON2Map(value);//解析路径
			
			if(pathMsgMap==null || pathMsgMap.size()==0){
				
				throw new PjException("流程路径指向信息不能为空！");
			}
			
			String  from=(String)pathMsgMap.get("from");//流程线起始位置
			String  to=(String)pathMsgMap.get("to");//流程线结束位置指向
			String  text=(String)pathMsgMap.get("text");//流程线信息
			
			String textPosX="";
			String textPosY="";
			if(!StringHelper.isEmpty(text)){//流程线名称
				
				Map<String,Object> pathDescMap=JsonToMap.parseJSON2Map(text);//流程线描述节点
				
				if(pathDescMap!=null && pathDescMap.size()>0){
					
					text=(String)pathDescMap.get("text");//获取流程描述信息
					
					String textPos=(String)pathDescMap.get("textPos");//获取流程描述信息
					Map<String,Object> textPosMap=JsonToMap.parseJSON2Map(textPos);
					if(textPosMap!=null && textPosMap.size()>0){
						
						textPosX=(String)textPosMap.get("x");
						textPosY=(String)textPosMap.get("y");
						
						if(!StringHelper.isEmpty(textPosX) || StringHelper.isEmpty(textPosY)){
//							  <bpmndi:BPMNEdge bpmnElement="sid-785A62D6-2F2D-46F7-9E98-74582DBCC6D9" id="BPMNEdge_sid-785A62D6-2F2D-46F7-9E98-74582DBCC6D9">
//						        <omgdi:waypoint x="300.0" y="300.0"/>
//						        <omgdi:waypoint x="300.0" y="355.0"/>
//						      </bpmndi:BPMNEdge>
							
							waypoint.append("\r\n<bpmndi:BPMNEdge bpmnElement=\"");
							waypoint.append(pathId);
							waypoint.append("\" id=\"BPMNEdge_");
							waypoint.append(pathId);
							waypoint.append("\">\r\n");
							//TODO标记写私
							waypoint.append(" <omgdi:waypoint x=\"300.0\" y=\"705.0\"/>\r\n");
							waypoint.append(" <omgdi:waypoint x=\"300.0\" y=\"789.0\"/>\r\n");
						
							waypoint.append("</bpmndi:BPMNEdge>\r\n");
						}
					}
					
					
//					String flowPosition=(String)pathDescMap.get("textPos");//流程位置点新
					
				}
				
			}
			
		
			
			String isPass = "";
			//获取流程线的扩展属性
			String props = (String)pathMsgMap.get("props");
			if(!StringHelper.isEmpty(props)){
				Map<String,Object> propsMap=JsonToMap.parseJSON2Map(props);
				String select = propsMap.get("select")== null?"":propsMap.get("select").toString();	
				if(!StringHelper.isEmpty(select)){
					Map<String,Object> selectMap=JsonToMap.parseJSON2Map(select);
					isPass = selectMap.get("value")== null?"":selectMap.get("value").toString();
				}
			}
			
			pathMsg.append("<sequenceFlow id=\"");
			pathMsg.append(pathId);
			pathMsg.append("\" sourceRef=\"");
			pathMsg.append(from);
			pathMsg.append("\" targetRef=\"");
			pathMsg.append(to);
			if(StringHelper.isEmpty(isPass)){
				pathMsg.append("\"/> \n\r");
			}else{
				pathMsg.append("\"> \n\r");
				pathMsg.append("<conditionExpression xsi:type=\"tFormalExpression\">");
				pathMsg.append("<![CDATA["+isPass+"]]>");
				pathMsg.append(" </conditionExpression>\n\r ");
				pathMsg.append(" </sequenceFlow>\n\r ");
			}
		}
		
		pathMsg.append("</process> \n\r");
		bpmndi.append(waypoint);
		bpmndi.append("\n\r</bpmndi:BPMNPlane> \n\r");
		return pathMsg.toString();
		
		
	}
	
	/**
	 * 根据节点id。节点属性遍历 转换成节点形状位置信息
	 * @param nodeId
	 * @param attr
	 * @param attr2 
	 * @return
	 */
	private String resolveNodeShape(String type,String nodeId,String attr){
		
		Map<String,Object> shapeMap=JsonToMap.parseJSON2Map(attr);//解析任务节点位置和大小信息
		if(shapeMap==null || shapeMap.size()==0){
			throw new PjException("任务节点的位置和大小信息不能为空");
		}
		
		String  x=(String)shapeMap.get("x");
		String  y=(String)shapeMap.get("y");
		String  width=(String)shapeMap.get("width");
		String  height=(String)shapeMap.get("height");
		if(StringHelper.isEmpty(width)){
			width="0";
		}
		if(StringHelper.isEmpty(height)){
			height = "0";
		}
		width = width.trim();
		height = height.trim();
		int iWidth;
		int iHeight;
		
		try {
			iWidth = ConvertHelper.toInt(width);
		} catch (Exception e) {
			e.printStackTrace();
			iWidth = 0;
		}
		try {
			iHeight = ConvertHelper.toInt(height);
		} catch (Exception e) {
			e.printStackTrace();
			iHeight = 0;
		}
		StringBuilder sb=new StringBuilder();
//		 <bpmndi:BPMNShape bpmnElement="task01" id="BPMNShape_task01">
//	        <omgdc:Bounds height="80.0" width="100.0" x="250.0" y="220.0"/>
//	      </bpmndi:BPMNShape>
		//如果是任务节点，则长度和高度不能小于  100和80
		if(!type.equalsIgnoreCase("start") && !type.equalsIgnoreCase("end")){
			if(iWidth<100){
				iWidth = 100;
			}
			if(iHeight<80){
				iHeight = 80;
			}
		}
		sb.append(" <bpmndi:BPMNShape bpmnElement=\"");
		sb.append(nodeId);
		sb.append("\" id=\"BPMNShape_");
		sb.append(nodeId);
		sb.append("\"> \n\r");
		sb.append(" <omgdc:Bounds height=\" ");
		sb.append(iHeight);
		sb.append("\" width=\"");
		sb.append(iWidth);
		sb.append("\" x=\"");
		sb.append(x);
		sb.append("\" y=\"");
		sb.append(y);
		sb.append("\"/>\n\r </bpmndi:BPMNShape> \n\r");
		
		return sb.toString();
		
	}
	
	
	/**
     * 根据节点id，和节点属性，节点类型组装节点
     * @param nodeId
     * @param nodeProps
     * @param nodeType
     * @return
     */
	private String resolveNodeProps(String nodeId,String nodeProps,String nodeType){
		
		if(StringHelper.isEmpty(nodeProps)){
			
			throw  new PjException("任务节点内容为空");
		}
		Map<String,Object> nodeMap=JsonToMap.parseJSON2Map(nodeProps);//解析节点
		
		String name=(String)nodeMap.get("name");//节点任务名
		String candidateGroups=(String)nodeMap.get("candidateGroups");//角色
		String documentation=(String)nodeMap.get("documentation");//说明
		String isSequential=(String)nodeMap.get("isSequential");//是否并行
		String extensionElements=(String)nodeMap.get("extensionElements");//表单属性
		extensionElements=extensionElements==null?"":extensionElements;
		
		if(!StringHelper.isEmpty(name)){
			
			Map<String,Object> valueMap=JsonToMap.parseJSON2Map(name);
			name=(String)valueMap.get("value");
		}
		if(!StringHelper.isEmpty(candidateGroups)){
			
			Map<String,Object> valueMap=JsonToMap.parseJSON2Map(candidateGroups);
			candidateGroups=(String)valueMap.get("value");
		}
		if(!StringHelper.isEmpty(documentation)){
			
			Map<String,Object> valueMap=JsonToMap.parseJSON2Map(documentation);
			documentation=(String)valueMap.get("value");
		}
		if(!StringHelper.isEmpty(isSequential)){
			
			Map<String,Object> valueMap=JsonToMap.parseJSON2Map(isSequential);
			isSequential=(String)valueMap.get("value");
		}
		
		StringBuilder node=new StringBuilder();//存放任务节点xml
		if(ISystemConstant.TASK_TYPE_START.equals(nodeType)){
			
//			extensionElements=justStartFormProps(extensionElements);//组装开始节点的表单属性
			node.append(" <startEvent id=\"");
			node.append(nodeId);
			node.append("\" name=\"");
			node.append(name);
			node.append("\">   ");
//			node.append(extensionElements);
			node.append(" </startEvent> \n\r ");
			
			return node.toString();
			
		}else if(ISystemConstant.TASK_TYPE_CHECK.equals(nodeType) 
				 || ISystemConstant.TASK_TYPE_TASK.equals(nodeType) 
				 || ISystemConstant.TASK_TYPE_NOTIFY.equals(nodeType)){//知会、审核、任务节点的直接从数据库中取值
//		TODO 20170317不在判断角色	
//			if(StringHelper.isEmpty(candidateGroups)){
//				
//				throw new PjException("任务节点的人员角色不能为空");
//			}
//			<userTask id="usertask1" name="多实例任务" activiti:assignee="${_assignee_}">
//		      <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="_assigneeList_" activiti:elementVariable="_assignee_">
//		        <completionCondition>${nrOfCompletedInstances/nrOfInstances == 1}</completionCondition>
//		      </multiInstanceLoopCharacteristics>
//		    </userTask>
//			extensionElements=pubParamService.getFormProp(nodeType);
		
			node.append("\n\r <userTask id=\"");
			node.append(nodeId);
			node.append("\" name=\"");
			node.append(name);
			node.append("\"");
//			node.append("\" activiti:assignee=\"${");
//			node.append(ISystemConstant.PROCESS_NODE_PART_PERSION);
			
			
			if(!StringHelper.isEmpty(candidateGroups)){
				Map<String, Object> candidateGroupMap = JsonToMap.parseJSON2Map(candidateGroups);
				List<Map> userList = (List<Map>)candidateGroupMap.get("userList");
				List<Map> roleList = (List<Map>)candidateGroupMap.get("roleList");
				String userIds = "";
				String roleIds = "";
				for (Map map : userList) {
					if(StringHelper.isEmpty(userIds)){
						userIds = (String)map.get("id");
					}else{
						userIds += ","+(String)map.get("id");
					}
				}
				for (Map map : roleList) {
					if(StringHelper.isEmpty(roleIds)){
						roleIds = (String)map.get("id");
					}else{
						roleIds += ","+(String)map.get("id");
					}
				}
				if(!StringHelper.isEmpty(userIds)){
					node.append(" activiti:candidateUsers=\'");
					node.append(userIds);
					node.append("\' ");
				}
				if(!StringHelper.isEmpty(roleIds)){
					node.append(" activiti:candidateGroups=\'");
					node.append(roleIds);
					node.append("\' ");
				}
			}
			node.append("/> \n\r ");
//			if(!StringHelper.isEmpty(documentation)){
//				node.append(" <documentation>");
//				node.append(documentation);
//				node.append("</documentation> \n\r");
//				
//			}
//			if(StringHelper.isEmpty(isSequential)){
//				
//				isSequential="false";
//			}
//			node.append(extensionElements);
//			
//			node.append("\n\r <multiInstanceLoopCharacteristics isSequential=\"");
//			node.append(isSequential);
//			node.append("\" activiti:collection=\"");
//			node.append(ISystemConstant.PROCESS_NODE_PART_PERSION_LIST);
//			node.append("\" activiti:elementVariable=\"");
//			node.append(ISystemConstant.PROCESS_NODE_PART_PERSION);
//			node.append("\">");
//			node.append("\n\r <completionCondition> \n\r");
//			node.append(ISystemConstant.PROCESS_RATIO);
//			node.append("\n\r </completionCondition> \n\r  </multiInstanceLoopCharacteristics>  \n\r");
//			node.append("\n\r </userTask> \n\r");
			
		   return node.toString();			
		}else if(ISystemConstant.TASK_TYPE_FORK.equals(nodeType)){//高级网关
			
			node.append(" <exclusiveGateway id=\"");
			node.append(nodeId);
			node.append("\" name=\"");
			node.append(name);
			node.append("\"> ");
			if(!StringHelper.isEmpty(documentation)){
				
				node.append(" \n\r <documentation> ");
				node.append(documentation);
				node.append(" </documentation> \n\r");
			}
			node.append("   </exclusiveGateway>\n\r ");
			
			return node.toString();
			
		}else if(ISystemConstant.TASK_TYPE_END.equals(nodeType)){
			
			node.append(" \n\r <endEvent id=\"");
			node.append(nodeId);
			node.append("\" name=\"");
			node.append(name);
			node.append("\"> \n\r");
            if(!StringHelper.isEmpty(documentation)){
				
				node.append(" <documentation> \n\r");
				node.append(documentation);
				node.append(" \n\r</documentation> ");
			}
        	node.append(" \n\r </endEvent> \n\r");
        	return node.toString();
			
		}else{
			
			return "";
		}
		
		
		
	}
	/**
	 * 组装开始节点的表单属性
	 * @param extensionElements
	 * @return
	 */
	private String  justStartFormProps(String extensionElements){
		
		if(StringHelper.isEmpty(extensionElements)){
			throw new PjException("开始节点的表单属性必填");
		}
		
		Map<String,Object> formPropsMap=JsonToMap.parseJSON2Map(extensionElements);//解析节点
		
		extensionElements=(String)formPropsMap.get("value");
		
		if(StringHelper.isEmpty(extensionElements)){
			throw new PjException("开始节点的表单属性必填");
		}
		
		formPropsMap=JsonToMap.parseJSON2Map(extensionElements);//解析节点
		
		extensionElements=(String)formPropsMap.get("formProp");
		
		if(StringHelper.isEmpty(extensionElements)){
			throw new PjException("开始节点的表单属性必填");
		}
		
		formPropsMap=JsonToMap.parseJSON2Map(extensionElements);//解析开始节点的表单
		if(formPropsMap==null || formPropsMap.size()==0){
			throw new PjException("开始节点的表单属性不能为空");
		}
		
		StringBuilder formStr=new StringBuilder();
		
		formStr.append(" \n\r<extensionElements> \n\r");
		
//		"formProp":{
//			 "name":{"id":"name","name":"名称","type":"string","value":""},
//			 "fileName":{"id":"fileName","name":"文件名","type":"file","value":""},
//			 "status":{"id":"status",
//			           "name":"状态",
//					   "type":"enum",
//					   "value":[
//					            {"enum_key":"01","enum_value":"审核通过"},
//							    {"enum_key":"02","enum_value":"审核不通过"}
//							   ]
//			         }
//			 }
		for(Map.Entry<String,Object> entry:formPropsMap.entrySet()){//循环遍历出form表单属性name,fileName,status
			//name :
			String key=entry.getKey();
//			{"id":"name","name":"名称","type":"string","value":""}
			String value=(String)entry.getValue();
			if(StringHelper.isEmpty(value)){
				throw new PjException("开始节点表单属性内容不能为空");
			}
			
			Map<String,Object> innerPropsMap=JsonToMap.parseJSON2Map(value);//获取里面的表单属性id,name、type、value
			
			if(innerPropsMap==null || innerPropsMap.size()==0){
				throw new PjException("开始节点表单属性内容不能为空");
			}
			
			String id=(String)innerPropsMap.get("id");
			String name=(String)innerPropsMap.get("name");
			String type=(String)innerPropsMap.get("type");
			
			formStr.append("  \n\r<activiti:formProperty id=\"");
			formStr.append(id);
			formStr.append("\" name=\"");
			formStr.append(name);
			formStr.append("\" type=\"");
			formStr.append(type);
			
			if("enum".equals(type)){//枚举型
				formStr.append("\">  \n\r");
				Object enumVal=innerPropsMap.get("value");
				 if(enumVal instanceof List){
					 List<Map<String,Object>> list=(List<Map<String,Object>>)enumVal;
					 for(Map<String,Object> values:list){
						 
						 String enum_key=(String)values.get("enum_key");
						 String enum_value=(String)values.get("enum_value");
//						 <activiti:value id="锁定" name="0"/>
						 
						 formStr.append(" <activiti:value id=\"");
						 formStr.append(enum_key);
						 formStr.append("\" name=\"");
						 formStr.append(enum_value);
						 formStr.append("\"/> \n\r ");
					 }
				 }
				 formStr.append(" </activiti:formProperty> \n\r ");
				 
			}else{//不是枚举类型直接结束
				
				formStr.append("\"/> \n\r ");
			}
			
			
			
		}
		formStr.append(" \n\r</extensionElements> \n\r");
			
		return formStr.toString();
		
	}
	
	
}
